<?php
/**
 * Nordic Repository
 * 
 * LICENSE
 * 
 * The new BSD license is applied on this source-file. For further
 * information please visit http://license.nordic-dev.de/newbsd.txt
 * or send an email to andre.moelle@gmail.com.
 */

/**
 * Load necessary classes.
 */
Zend_Loader::loadClass('Zend_Controller_Action_Helper_Abstract');
Zend_Loader::loadClass('Zend_Config_Exception');

Zend_Loader::loadClass('Nordic_Util');


/**
 * This class provides a uniform interface for loading config-classes.
 * 
 * You do not have to depend on concrete classes but 
 * 
 * @category   Nordic
 * @package    Nordic_Config
 * @copyright  2007 Nordic Development
 * @license    http://license.nordic-dev.de/newbsd.txt (New-BSD license)
 * @author     Andre Moelle <andre.moelle@gmail.com>
 * @version    $Id: Config.php 3 2007-07-08 09:21:42Z andre.moelle $
 */
class Nordic_Config
{
	/**
	 * Default prefix for config-classes.
	 * 
	 * @const string
	 */
	const DEFAULT_PREFIX = 'Zend_Config_';
	
	/**
	 * Extensions and their classnames.
	 * 
	 * <code>
	 * $_extensions = array(
	 * 	'php' => 'Nordic_Config_Php',
	 * 	'ini' => 'Zend_Config_Ini'
	 * );
	 * </code>
	 * 
	 * @var array
	 */
	private $_extensions = array();
	
	/**
	 * Instance of this class.
	 * 
	 * @var Nordic_Config
	 */
	private static $_instance = null;
	
	/**
	 * Constructor.
	 * 
	 * Sets the extensions and loads the default extensions.
	 * 
	 * @param array $extensions 
	 */
	private function __construct (array $extensions)
	{
		$this->_loadExtensions();
		$this->setExtensions($extensions);
	}
	
	/**
	 * Loads and instantiates a new Zend_Config-object.
	 * 
	 * @param string $class classname of the returned object
	 * @param string $name name of the config-object
	 * @param array $options options
	 * @return Zend_Config
	 */
	private function _instantiate ($path, array $options = array())
	{
		$class = $this->getClass(Nordic_Util::getExtension($path));
		Zend_Loader::loadClass($class);
		
		$options['section'] = gv($options['section']);
		$options['allowModifications'] = gv($options['allowModifications'], false);
		
		return new $class($path, $options['section'], $options['allowModifications']);
	}
	
	/**
	 * Loads the default-extensions.
	 * 
	 * @param void
	 * @return void
	 */
	private function _loadExtensions ()
	{
		$array = glob(
			NORDIC_LIB . str_replace('_', '/', self::DEFAULT_PREFIX) .
			'*.php'
		);
		
		if(!$array)
		{
			return array();
		}
		
		foreach($array as $path)
		{
			$base = basename($path, '.php');
			$this->extend($base, self::DEFAULT_PREFIX . $base);
		}
	}
	
	/**
	 * Transforms the suffix.
	 * 
	 * @param string $suffix suffix for filenames
	 * @return string
	 */
	private function _transform ($suffix)
	{
		return strtolower($suffix);
	}
	
	/**
	 * Adds a new extension to the internal array.
	 * 
	 * @param string $suffix filename-suffix
	 * @param string $classname classname which belongs to the suffix
	 * @return void
	 */
	public function extend ($suffix, $classname)
	{
		$this->_extensions[$this->_transform($suffix)] = $classname;
	}
	
	/**
	 * Returns the classname if it exists.
	 * 
	 * Otherwise a Zend_Config_Exception will be thrown.
	 * 
	 * @throws Zend_Config_Exception
	 * @param string $suffix suffix of the filename
	 * @return string
	 */
	public function getClass ($suffix)
	{
		$suffix = $this->_transform($suffix);
		$extensions = $this->getExtensions();
		
		if(!array_key_exists($suffix, $extensions))
		{
			throw new Zend_Config_Exception(
				'Class for the suffix "' . $suffix . '" does not exist'
			);
		}
		
		return $extensions[$suffix];
	}
	
	/**
	 * Returns the extensions.
	 * 
	 * @param void
	 * @return array
	 */
	public function getExtensions ()
	{
		return $this->_extensions;
	}
	
	/**
	 * Returns the instance of this config-class.
	 * 
	 * @param array $extensions array of extensions and their classes
	 * @return Nordic_Config
	 */
	public static function getInstance (array $extensions = array())
	{
		if(self::$_instance == null)
		{
			self::$_instance = new self($extensions);
		}
		
		return self::$_instance;
	}
	
	/**
	 * Loads a config-file.
	 * 
	 * @throws Zend_Config_Exception
	 * @param string $name name of the config (with suffix)
	 * @param array $options array with options
	 * @return Zend_Config
	 */
	public function load ($name, array $options = array())
	{
		$path = NORDIC_CONFIG . $name;
		
		if(!file_exists($path))
		{
			throw new Zend_Config_Exception(
				'Config "' . $path . '" does not exist'
			);
		}
		
		return $this->_instantiate($path, $options);
	}
	
	/**
	 * Sets the extensions.
	 * 
	 * @param array $extensions array of extensions and their classnames
	 * @param boolean $delete if true the old extensions are deleted
	 * @return void
	 */
	public function setExtensions (array $extensions, $delete = false)
	{
		if($delete)
		{
			$this->_extensions = array();
		}
		
		foreach($extensions as $suffix => $class)
		{
			$this->extend($suffix, $class);
		}
	}
}
?>